use crate::controller::auth::{self};
use crate::controller::test::{self};
use crate::controller::upload::{upload, upload_file};
use crate::controller::{socket, upload};
use crate::middleware::auth::auth_fn_mid;
use crate::state::AppState;
use axum::routing::{delete, get, post};
use axum::{middleware, Extension, Router};
use tower::ServiceBuilder;
use tower_http::cors::{Any, CorsLayer};
use tower_http::services::ServeDir;
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
use tower_sessions::{MemoryStore, SessionManagerLayer};

/**
 * 中间件 依托 tower， tower_http
 */
pub fn init_apis(app_state: AppState) -> Router {
    // 跨域解决
    let cors = CorsLayer::new().allow_origin(Any);

    // session
    let session_store = MemoryStore::default();
    let session_layer = SessionManagerLayer::new(session_store).with_secure(false);

    // 日志打印
    let log = TraceLayer::new_for_http();

    let api = Router::new()
        // 静态资源"
        .nest_service("/assets", ServeDir::new("./assets"))
        .route("/static", get(upload::show_files_root))
        .route("/static/*path", get(upload::show_files_listing))
        // 默认重定向
        // .fallback(upload::show_files_root);
        .merge(not_auth_routes())
        .merge(need_auth_routers())
        .layer(
            ServiceBuilder::new()
                .layer(log)
                .layer(cors)
                // 注入状态共享 Arc设置不可变保证多线程数据一致性
                // .layer(Extension(Arc::new(app_state)))
                .layer(session_layer),
        )
        .layer(Extension(app_state));
    api
}

pub fn not_auth_routes() -> Router {
    Router::new()
        .route("/ws", get(socket::sokcet_handler))
        .route("/sse", get(socket::sse_handler))
        .route("/post_step", post(socket::post_step))
        .layer(
            // 打印请求头具体信息 调试 socket
            TraceLayer::new_for_http()
                .make_span_with(DefaultMakeSpan::default().include_headers(true)),
        )
        .route("/", get(|| async { "Hello, World!" }))
        .route("/login", post(auth::login))
        .route("/register", post(auth::register))
        .route("/captcha", get(auth::captcha))
        .route("/timed_task", get(test::timed_task))
        .route("/set_redis/:info", get(test::set_redis))
        .route("/get_redis", get(test::get_redis))
        .route("/params_check", get(test::params_check))
        .nest(
            "/upload",
            Router::new()
                .route("/html", get(upload_file))
                .route("/", post(upload)),
        )
}

pub fn need_auth_routers() -> Router {
    Router::new()
        .nest(
            "/test",
            Router::new()
                .route("/", get(test::query).post(test::add).put(test::put))
                .route("/:id", delete(test::del).get(test::get_by_id))
                .route("/list", get(test::list)),
        )
        // 鉴权
        .layer(middleware::from_fn(auth_fn_mid))
}
